package com.example.video.controller;

import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.example.video.Enum.videoStatus;
import com.example.video.common.Result;
import com.example.video.entity.*;
import com.example.video.service.IDeviceService;
import com.example.video.service.IVideoLogService;
import com.example.video.service.impl.AccountServiceImpl;
import com.example.video.service.impl.OuterAccountServiceImpl;
import com.example.video.service.impl.PlatformServiceImpl;
import com.example.video.service.impl.VideoServiceImpl;
import com.example.video.util.RoleUtils;
import com.example.video.util.laixiOperate.Operate;
import com.example.video.util.queue.DownQueueManager;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author qiusuyang
 * @since 2024-04-13
 */
@Slf4j
@RestController
@RequestMapping("/account")
public class AccountController {

    @Resource
    private AccountServiceImpl accountService;

    @Resource
    private VideoServiceImpl videoService;

    @Resource
    private IVideoLogService videoLogService;

    @Resource
    private PlatformServiceImpl platformService;

    @Resource
    private DownQueueManager downQueueManager;


    @Resource
    private OuterAccountServiceImpl outerAccountService;

    @Resource
    private IDeviceService deviceService;

    @Resource
    private Operate laixiOperate;

    /**
     * @desc 通过页数和大小获取账号显示列表
     * 具体显示：id,源作者名称,源作者平台,源作者主页，源作者头像，下载进度。
     * @param page 页数
     * @param limit 每页大小
     * @return 获取的账户列表
     */
    @PostMapping("/accountList")
    public Result<List<AdminShowAccount>> getAccountList(Integer page, Integer limit){
        log.info("page:"+page+" limit:"+limit);
        Result<List<AdminShowAccount>> rs = new Result<>();
        List<Account> list = accountService.getList(page, limit);
        List<AdminShowAccount> resultList  = new ArrayList<>();
        if( list.isEmpty() ){
            rs.setCode(-1);
            rs.setData(null);
            rs.setMsg("获取失败！");
        }else{
            for (Account item : list){
                videoService.getListByAccountId(item.getId());
                AdminShowAccount adminShowAccount = new AdminShowAccount();
                adminShowAccount.setAccountId(item.getId());
                adminShowAccount.setName(item.getName());
                adminShowAccount.setPlatform(item.getPlatform());
                adminShowAccount.setAccountUrl(item.getUrl());
                adminShowAccount.setAvatarUrl(item.getAvatarUrl());
                adminShowAccount.setTotalDownload(
                        Db.lambdaQuery(Video.class)
                            .eq(Video::getAccountId, item.getId())
                            .ge(Video::getStatus, videoStatus.DOWNLOADING.getStatus())
                            .count()
                );
                adminShowAccount.setTotalUpload(
                        Db.lambdaQuery(Video.class)
                                .eq(Video::getAccountId, item.getId())
                                .eq(Video::getStatus, videoStatus.DEVICEUPLOAD.getStatus())
                                .count()
                );
                adminShowAccount.setTotal(item.getTotal());
                // adminShowAccount.setDownLoading((int) videoList.stream().filter(video -> video.getDownLoading() == 1).count());

                resultList.add(adminShowAccount);
            }

//            log.info(resultList);
            rs.setCode(0);
            rs.setData(resultList);
            rs.setCount(accountService.getCount());
            rs.setMsg("获取成功！");
        }
        return rs;
    }

    /**
     * 通过名字模糊查询源作者相关信息
     * @param page
     * @param limit
     * @param name
     * @return 包含accountId、name、platform、accountUrl、avatarUrl、totalVideo、total
     */

    @PostMapping("/accountSearch")
    public Result<List<AdminShowAccount>> searchAccount(Integer page, Integer limit,Authentication authentication,
                                                        @RequestParam(defaultValue = "") String name,
                                                        @RequestParam(defaultValue = "") String platformName){
        Result<List<AdminShowAccount>> rs = new Result<>();
        log.info("AccountCTRL -> accountSearch -> msg: page = " + page + " limit = " + limit + " name = " + name + " platformName = " + platformName);
        Integer platformid = 0;
        if( !"".equals(platformName)){
            Platform platform = platformService.getItemByName(platformName);
            if(platform != null){
                platformid = platform.getId();
            }else{
                rs.setMsg("无此平台！");
                rs.setCode(-1);
                rs.setData(null);
                return rs;
            }
        }

//        log.info("api -> accountSearch -> msg: platformid "+platformid);
        List<Account> list = accountService.search(page, limit,name, platformid );
        List<AdminShowAccount> resultList  = new ArrayList<>();
        if( list.isEmpty() ){
            rs.setCode(-1);
            rs.setData(null);
            rs.setMsg("获取失败！无数据！");
        }else{
            for (Account item : list){
                videoService.getListByAccountId(item.getId());
                AdminShowAccount adminShowAccount = new AdminShowAccount();
                adminShowAccount.setAccountId(item.getId());
                adminShowAccount.setName(item.getName());
                adminShowAccount.setPlatform(item.getPlatform());
                adminShowAccount.setAccountUrl(item.getUrl());
                adminShowAccount.setAvatarUrl(item.getAvatarUrl());
                adminShowAccount.setTotalDownload(
                        Db.lambdaQuery(Video.class)
                                .eq(Video::getAccountId, item.getId())
                                .ge(Video::getStatus, videoStatus.DOWNLOADING.getStatus())
                                .count()
                );
                adminShowAccount.setTotalUpload(
                        Db.lambdaQuery(Video.class)
                                .eq(Video::getAccountId, item.getId())
                                .eq(Video::getStatus, videoStatus.DEVICEUPLOAD.getStatus())
                                .count()
                );
                adminShowAccount.setTotal(item.getTotal());
                // adminShowAccount.setDownLoading((int) videoList.stream().filter(video -> video.getDownLoading() == 1).count());

                resultList.add(adminShowAccount);
            }

//            log.info(resultList);
            rs.setCode(0);
            rs.setData(resultList);
            rs.setCount(accountService.getCount());
            rs.setMsg("获取成功！");
        }
        return rs;
    }


    /**
     * 账户添加或修改。上传需要重新对用户进行检索,修改无需重新检索
     *
     * @param adminShowAddAccount
     * @return
     */
    @ResponseBody
    @PostMapping("/upload")
    public Result<String> uploadAccount(@RequestBody AdminShowAddAccount adminShowAddAccount) {
        //获取当前登录用户的认证信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        // 获取用户的所有权限
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
//        log.info("account -> upload -> msg: 接收到请求！");
        Result<String> rs = new Result();

//        log.info("account -> upload -> msg: " + adminShowAddAccount);
        // 如果数据库中存在同url的账户，则直接返回
        if (adminShowAddAccount.getAccountId() == 0) {
            Account tempAccount = accountService.getItemByUrl(adminShowAddAccount.getUrl());
            if (tempAccount != null) {
                rs.setMsg("存在相同账户！" );
                rs.setCode(-1);
                rs.setData("");
                rs.setCount(0);
                return rs;
            }
        }

        Account account = new Account();
        if (adminShowAddAccount.getAccountId() != 0) {
            account = accountService.getItem(adminShowAddAccount.getAccountId());
        }
        account.setId(adminShowAddAccount.getAccountId());
        account.setUrl(adminShowAddAccount.getUrl());
        account.setPlatform(adminShowAddAccount.getPlatform());
        account.setLanguage(adminShowAddAccount.getLanguage());
        account.setToLanguage(adminShowAddAccount.getToLanguage());
        // 检查认证信息是否存在及其权限是否为空
        if (authentication != null && authentication.getAuthorities() != null) {
            // 遍历所有的权限
            for (GrantedAuthority authority : authentication.getAuthorities()) {
                // 提取并格式化角色
                List<String> roles = RoleUtils.extractRoles(authorities);
                // 遍历提取的角色列表并设置到 account 对象中
                log.info("accountCtr -> upload -> 获取到的角色列表：" + roles);
                account.setRole(roles.toString());

            }

        }

        // 6.5 新增：绑定设备ID，若绑定失败，则直接返回错误消息
        User user = Db.lambdaQuery(User.class)
                .eq(User::getRole, account.getRole())
                .select(User::getGroupId)
                .list()
                .get(0);
        Result<String> groupRs = null;
        try {
            groupRs = laixiOperate.createDevice();
        } catch (URISyntaxException | InterruptedException e) {
            log.info("accountCtr -> upload -> 来喜服务连接失败！！"+e.getMessage());
            rs.setCode(-1);
            rs.setMsg("来喜服务器连接错误！请联系管理员！");
            return rs;
        }
        if(groupRs.getCode() == 0 && Db.lambdaQuery(Account.class).eq(Account::getDeviceId, groupRs.getData()).count() == 0){
            account.setDeviceId(groupRs.getData());
            Device device = new Device();
            device.setDeviceId(groupRs.getData());
            device.setStatus(0);
            // 提取并格式化角色
            List<String> formattedRoles = RoleUtils.extractRoles(authorities);
            device.setRole(formattedRoles.toString());
//            Db.lambdaQuery(Device.class).getBaseMapper().insert(new Device());
            Db.save(device);
        }else{
            log.info("accountCtr -> upload -> 设备操作返回值："+groupRs);
            rs.setMsg("添加账户错误：绑定设备失败！");
            rs.setCode(-1);
            rs.setData("");
            rs.setCount(0);
            return rs;
        }


        // 如果是修改，则保存后直接退出，不进行重新检索
        int accountId;
        if (account.getId() != 0 && account.getId() != null) {
            accountId = accountService.save(account);
            if (accountId != 0) {
                rs.setCode(0);
                rs.setMsg("修改成功！");
            } else {
                rs.setCode(-1);
                rs.setMsg("修改失败！");
            }
//            log.info("account -> upload -> msg: outer = "+adminShowAddAccount.getOuters());
            for (AdminShowOuter outer : adminShowAddAccount.getOuters()) {

                Platform platform = platformService.getItem(outer.getPlatformId());
                OuterAccount outerAccount = new OuterAccount();
                outerAccount.setId(outer.getOuterId());
                outerAccount.setAccountId(accountId);
                outerAccount.setPlatformId(outer.getPlatformId());
                outerAccount.setPlatformName(platform.getPlatformName());
                outerAccount.setUserAccount(outer.getUserAccount());
                outerAccount.setUserPwd(outer.getUserPwd());

            }
            return rs;

        } else {
            accountId = accountService.save(account);
        }

        // 如果是首次上传，则进行首次检索
        if (accountId != 0) {
            log.info("account -> upload -> msg: 首次上传account！");


            for (AdminShowOuter outer : adminShowAddAccount.getOuters()) {

                Platform platform = platformService.getItem(outer.getPlatformId());
                OuterAccount outerAccount = new OuterAccount();
                outerAccount.setId(outer.getOuterId());
                outerAccount.setAccountId(accountId);

                outerAccount.setPlatformId(outer.getPlatformId());
                outerAccount.setPlatformName(platform.getPlatformName());

                outerAccount.setUserAccount(outer.getUserAccount());
                outerAccount.setUserPwd(outer.getUserPwd());

                outerAccountService.save(outerAccount);
            }

            // 5.22 新增
            if(downQueueManager.addTask(account, null)){
                    rs.setCode(0);
                    rs.setMsg("上传成功！");
                    rs.setCount(1);
                    rs.setData(null);
            }else{
                rs.setCode(-1);
                rs.setMsg("上传失败！");
                rs.setCount(1);
                rs.setData(null);
            }

        } else {
            accountService.delete(account.getId());

        }
        rs.setData("修改成功！");
        rs.setCount(0);
        rs.setCode(0);
        rs.setMsg("修改成功！");


        return rs;
    }


    /**
     * @param id 待删除数据的id
     * @return 是否删除成功
     */
    @ResponseBody
    @PostMapping("/delete")
    public Result<Boolean> deleteItem(Integer id) {
        log.info("AccountCtrl -> delete ->msg: 接收到的数据：" + id);
        Result<Boolean> rs = new Result<>();
        Account account = accountService.getItem(id);
        String deviceId = account.getDeviceId();
        // 删除设备
        Device device = deviceService.getItemByDeviceId(deviceId);
        deviceService.delete(deviceId);
        String groupId = "";
        // 如果是未绑定
        // 获取分组id
        if(device.getStatus() == 0){
            try {
                groupId = laixiOperate.getCacheGroup();
            } catch (URISyntaxException | InterruptedException e) {
                log.info("accountCtrl -> delete -> msg: 连接来喜服务失败！！"+e.getMessage());
                rs.setCode(-1);
                rs.setMsg("来喜服务连接错误！请联系管理员！");
                return rs;
            }
        }else{
            groupId = Db.lambdaQuery(User.class)
                    .select(User::getGroupId)
                    .eq(User::getRole,account.getRole())
                    .list()
                    .get(0)
                    .getGroupId()
            ;
        }
        try {
            laixiOperate.deleteDevice(groupId, List.of(deviceId));
        } catch (URISyntaxException | InterruptedException e) {
            log.info("accountCtrl -> delete -> msg: 连接来喜服务失败！！"+e.getMessage());
            rs.setCode(-1);
            rs.setMsg("来喜服务连接错误！请联系管理员！");
            return rs;
        }
        log.info("accountCtrl -> delete -> msg: 进行设备删除" );
        Boolean flag = accountService.delete(id);

        List<Video> list = videoService.getListByAccountId(id);
        for (Video video : list) {
            videoService.delete(video.getId());
            videoLogService.deleteListByVideoId(video.getId());
        }
        rs.setData(flag);
        if (flag) {
            rs.setCode(200);
            rs.setMsg("成功!");
        } else {
            rs.setCode(500);
            rs.setMsg("失败!");
        }
        return rs;
    }




    /****************************************************** 暂时无用  ******************************************************/

    /**
     * @desc 通过ID获取账户项信息
     * @param id 账户项的ID，用于查询特定的账户项
     * @return 返回一个Result对象，其中包含账户项信息和操作结果的状态码、消息
     */

    @PostMapping("/accountItem")
    public Result<Account> getAccountItem(Integer id){
        Result<Account> rs = new Result<>();
        Account item = accountService.getItem(id);
        if(item != null){
            rs.setData(item);
            rs.setMsg("获取成功！");
            rs.setCode(0);
        }else {
            rs.setCode(-1);
            rs.setData(null);
            rs.setMsg("获取失败！");
        }
        rs.setCount(1);
        return rs;
    }


}
